﻿namespace IObserableAndIObserver
{
    internal class Program
    {
        static void Main(string[] args)
        {
            WeatherDataPublisher publisher = new WeatherDataPublisher();
            CurrentConditionDisplay currentDisplay = new CurrentConditionDisplay();
            StatisticsConditionDisplay statisticsDisplay = new StatisticsConditionDisplay();

            var testxx = new TestXX();
            var x = testxx.Test;

            //订阅当前天气展示板
            IDisposable currentDisplayUnsubscriber = publisher.Subscribe(currentDisplay);
            //订阅气温统计展示板
            IDisposable statisticsDisplayUnsubscriber = publisher.Subscribe(statisticsDisplay);

            for (int i = 0; ; i++)
            {
                WeatherData weatherData = new WeatherData();
                Console.WriteLine("请输入温度,湿度,压力");
                string input = Console.ReadLine();
                var array = input.Split(',');
                weatherData.temperature = array[0];
                weatherData.humility = array[1];
                weatherData.pressure = array[2];
                Console.WriteLine("");
                //将输入的新的天气数据传给天气数据发布器
                publisher.ReciveNewData(weatherData);
                Console.WriteLine("=============================");
            }
        }
    }



    class WeatherData
    {
        /// <summary>
        /// 气温
        /// </summary>
        public string temperature { get; set; }
        /// <summary>
        /// 湿度
        /// </summary>
        public string humility { get; set; }
        /// <summary>
        /// 气压
        /// </summary>
        public string pressure { get; set; }
    }

    class TestXX
    {
        public IObservable<WeatherData> Test { get; set; }
    }

    class WeatherDataPublisher : IObservable<WeatherData>
    {
        List<IObserver<WeatherData>> observers = new List<IObserver<WeatherData>>();
        /// <summary>
        /// 订阅主题，将观察者添加到列表中
        /// </summary>
        /// <param name="observer"></param>
        /// <returns></returns>
        public IDisposable Subscribe(IObserver<WeatherData> observer)
        {
            observers.Add(observer);
            return new Unsubscribe(this.observers, observer);
        }

        /// <summary>
        /// 取消订阅类
        /// </summary>
        private class Unsubscribe : IDisposable
        {
            List<IObserver<WeatherData>> observers;
            IObserver<WeatherData> observer;
            public Unsubscribe(List<IObserver<WeatherData>> observers ,IObserver<WeatherData> observer)
            {
                this.observer = observer;
                this.observers = observers;
            }

            public void Dispose()
            {
                if (this.observers != null)
                {
                    this.observers.Remove(observer);
                }
            }
        }
        /// <summary>
        /// 通知已订阅的观察者
        /// </summary>
        /// <param name="weatherData"></param>
        private void Notify(WeatherData weatherData)
        {
            foreach (var observer in observers)
            {
                observer.OnNext(weatherData);
            }
        }
        /// <summary>
        /// 接收最新的天气数据
        /// </summary>
        /// <param name="weatherData"></param>
        public void ReciveNewData(WeatherData weatherData)
        {
            Notify(weatherData);
        }
    }

    // 观察者 1
    abstract class WeatherDisplayBase : IObserver<WeatherData>
    {
        public virtual void OnCompleted()
        {
        }
        public virtual void OnError(Exception error)
        {
        }
        public abstract void OnNext(WeatherData value);
    }

    class CurrentConditionDisplay : WeatherDisplayBase
    {
        public override void OnNext(WeatherData value)
        {
            Console.WriteLine("------------------");
            Console.WriteLine("当前天气状况板");
            Console.WriteLine(string.Format("温度：{0}\n湿度：{1}\n气压：{2}",
                value.temperature, value.humility, value.pressure));
        }
    }

    class StatisticsConditionDisplay : WeatherDisplayBase
    {
        List<float> temperatures = new List<float>();
        public override void OnNext(WeatherData value)
        {
            float temperature;
            if (float.TryParse(value.temperature, out temperature))
            {
                temperatures.Add(temperature);
            }
            Console.WriteLine("------------------");
            Console.WriteLine("温度统计板");
            Console.WriteLine(string.Format("平均温度：{0}\n最高温度：{1}\n最低温度：{2}",
                temperatures.Average(), temperatures.Max(), temperatures.Min()));
        }
    }

}
